package math2;

/**
 * Lagrange basis on 8-node hexahedra element
 * 
 * @author hbui
 * 
 */
public class LagrangeFBOnHex8 extends PolynomialBasisOnRnToR {

	public LagrangeFBOnHex8() {

		addBasisFunction(
		/*
		 * N1 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 - xi) * (1 - eta) * (1 - zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { -(1 - eta) * (1 - zeta) / 8, -(1 - xi) * (1 - zeta) / 8,
						-(1 - xi) * (1 - eta) / 8 };
			}
		},
		/*
		 * N2 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 + xi) * (1 - eta) * (1 - zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { (1 - eta) * (1 - zeta) / 8, -(1 + xi) * (1 - zeta) / 8,
						-(1 + xi) * (1 - eta) / 8 };
			}
		},
		/*
		 * N3 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 + xi) * (1 + eta) * (1 - zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { (1 + eta) * (1 - zeta) / 8, (1 + xi) * (1 - zeta) / 8,
						-(1 + xi) * (1 + eta) / 8 };
			}
		},
		/*
		 * N4 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 - xi) * (1 + eta) * (1 - zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { -(1 + eta) * (1 - zeta) / 8, (1 - xi) * (1 - zeta) / 8,
						-(1 - xi) * (1 + eta) / 8 };
			}
		},
		/*
		 * N5 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 - xi) * (1 - eta) * (1 + zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { -(1 - eta) * (1 + zeta) / 8, -(1 - xi) * (1 + zeta) / 8,
						(1 - xi) * (1 - eta) / 8 };
			}
		},
		/*
		 * N6 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 + xi) * (1 - eta) * (1 + zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { (1 - eta) * (1 + zeta) / 8, -(1 + xi) * (1 + zeta) / 8,
						(1 + xi) * (1 - eta) / 8 };
			}
		},
		/*
		 * N7 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 + xi) * (1 + eta) * (1 + zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { (1 + eta) * (1 + zeta) / 8, (1 + xi) * (1 + zeta) / 8,
						(1 + xi) * (1 + eta) / 8 };
			}
		},
		/*
		 * N8 =
		 */
		new FunctionRnToR() {

			@Override
			public double valueAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return (1 - xi) * (1 + eta) * (1 + zeta) / 8;
			}

			@Override
			public double[] gradientAt(double... psi) {
				double xi = psi[0];
				double eta = psi[1];
				double zeta = psi[2];
				return new double[] { -(1 + eta) * (1 + zeta) / 8, (1 - xi) * (1 + zeta) / 8,
						(1 - xi) * (1 + eta) / 8 };
			}
		});
	}

	@Override
	public int getP() {
		return 2;
	}

	@Override
	public void setP(int p) {
	}

	@Override
	public Object clone() {
		return new LagrangeFBOnHex8();
	}

}
